package com.salton123.utils

import android.util.Log
import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.FFprobeKit
import com.arthenica.ffmpegkit.ReturnCode
import com.salton123.coroutine.Ret
import com.salton123.log.XLog
import java.io.File
import kotlin.coroutines.resume
import kotlinx.coroutines.suspendCancellableCoroutine

/**
 * Time:2022/1/19 5:14 下午
 * Author:
 * Description:
 */
object FFmpegCompressor {
    private const val TAG = "FFmpegCompressor"

    suspend fun totalNbFrames(filePath: String): Ret<Int> {
        return suspendCancellableCoroutine { continuation ->
            var totalFrames = -1
            FFprobeKit.getMediaInformationAsync(filePath) { session ->
                XLog.i(TAG, "[totalNbFrames] command:${session.command}")
                session.mediaInformation.streams.forEach { streamInfo ->
                    if ("video" == streamInfo.allProperties.optString("codec_type")) {
                        totalFrames = streamInfo.allProperties.optString("nb_frames").toIntOrNull() ?: 0
                        continuation.resume(Ret.Success(totalFrames))
                    }
                }
                continuation.resume(Ret.Failure(totalFrames))
            }
        }
    }

    suspend fun compress(filePath: String, callback: (Int) -> Unit): Ret<Int> {
        val totalFrames = totalNbFrames(filePath).getOrNull() ?: -1
        return suspendCancellableCoroutine { continuation ->
            val newFilePath = getCompressPath(filePath)
            val processors = Runtime.getRuntime().availableProcessors()
            val command = "-vcodec h264 -i $filePath -vcodec h264  -threads $processors $newFilePath"
            FFmpegKit.executeAsync(command, {
                Log.i(TAG, "completeCallback:$it")
                if (it.returnCode.value == ReturnCode.SUCCESS) {
                    callback.invoke(100)
                    continuation.resume(Ret.Success(100))
                } else {
                    callback.invoke(-1)
                    continuation.resume(Ret.Failure(-1))
                }
            }, {
            }, {
                callback.invoke(it.videoFrameNumber * 100 / totalFrames)
                continuation.resume(Ret.Success(it.videoFrameNumber * 100 / totalFrames))
            })
        }
    }

    open fun getCompressPath(filePath: String): String {
        val file = File(filePath)
        val fileName = file.name.replace(".mp4", "_compress.mp4")
        return file.parent + File.separator + fileName
    }
}